<template>
  <div class="app-container">
    <div class="header">
      <h1>Word模板生成器</h1>
      <p class="description">
        使用docxtemplater动态生成Word文档，支持模板变量替换和实时预览
      </p>
    </div>

    <el-card class="main-card">
      <div slot="header" class="clearfix">
        <span>模板配置</span>
        <el-button
          style="float: right; padding: 3px 0"
          type="text"
          @click="downloadTemplate"
        >
          下载示例模板
        </el-button>
      </div>

      <el-form :model="form" label-width="120px" class="demo-form">
        <el-form-item label="模板选择">
          <el-radio-group v-model="templateSource" @change="handleTemplateSourceChange">
            <el-radio label="upload">上传模板</el-radio>
            <el-radio label="local">本地模板</el-radio>
          </el-radio-group>
        </el-form-item>

        <!-- 上传模板区域 -->
        <el-form-item label="模板文件" v-if="templateSource === 'upload'">
          <el-upload
            class="upload-demo"
            action="#"
            :auto-upload="false"
            :on-change="handleTemplateUpload"
            :file-list="templateFiles"
            accept=".docx"
          >
            <el-button size="small" type="primary">点击上传</el-button>
            <div slot="tip" class="el-upload__tip">只能上传docx文件</div>
          </el-upload>
        </el-form-item>

        <!-- 本地模板选择区域 -->
        <el-form-item label="本地模板" v-if="templateSource === 'local'">
          <el-select v-model="selectedLocalTemplate" placeholder="请选择模板" style="width: 100%;">
            <el-option
              v-for="template in localTemplates"
              :key="template.value"
              :label="template.label"
              :value="template.value"
            >
              <span style="float: left">{{ template.label }}</span>
              <span style="float: right; color: #8492a6; font-size: 13px">{{ template.description }}</span>
            </el-option>
          </el-select>
          <div style="margin-top: 10px; color: #909399; font-size: 12px;">
            <p>模板文件存放在：src/assets/templates/ 目录下</p>
          </div>
        </el-form-item>

        <el-form-item label="姓名">
          <el-input v-model="form.name" placeholder="请输入姓名"></el-input>
        </el-form-item>

        <el-form-item label="职位">
          <el-input v-model="form.position" placeholder="请输入职位"></el-input>
        </el-form-item>

        <el-form-item label="公司">
          <el-input
            v-model="form.company"
            placeholder="请输入公司名称"
          ></el-input>
        </el-form-item>

        <el-form-item label="日期">
          <el-date-picker
            v-model="form.date"
            type="date"
            placeholder="选择日期"
            value-format="yyyy-MM-dd"
          ></el-date-picker>
        </el-form-item>

        <el-form-item label="薪资">
          <el-input-number
            v-model="form.salary"
            :min="0"
            :step="1000"
            placeholder="请输入薪资"
          ></el-input-number>
        </el-form-item>

        <el-form-item label="备注">
          <el-input
            type="textarea"
            :rows="3"
            v-model="form.remarks"
            placeholder="请输入备注信息"
          ></el-input>
        </el-form-item>

        <el-form-item>
          <el-button
            type="primary"
            :disabled="(templateSource === 'upload' && !templateFile) || (templateSource === 'local' && !selectedLocalTemplate)"
            @click="generateDocument"
            :loading="generating"
          >
            生成文档
          </el-button>
          <el-button type="primary" @click="getTestDoc">
            测试文档下载
          </el-button>
          <el-button @click="resetForm">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 文档预览区域 -->
    <el-card class="preview-card" v-if="previewUrl || previewDocument">
      <div slot="header" class="clearfix">
        <span>文档预览</span>
        <div style="float: right">
          <el-button 
            v-if="previewDocument"
            style="margin-right: 10px;" 
            type="text"
            @click="showPreview = !showPreview"
          >
            {{ showPreview ? '隐藏预览' : '显示预览' }}
          </el-button>
          <el-button 
            type="text"
            @click="downloadDocument"
          >
            下载文档
          </el-button>
        </div>
      </div>

      <div class="preview-content" v-if="!showPreview">
        <p>文档生成成功！您可以预览或下载文档。</p>
        <el-button type="success" @click="downloadDocument">
          <i class="el-icon-download"></i> 下载Word文档
        </el-button>
        <el-button type="info" @click="showPreview = true" v-if="previewDocument">
          <i class="el-icon-view"></i> 预览文档
        </el-button>
      </div>

      <!-- Word文档预览组件 -->
      <div class="word-preview" v-if="showPreview && previewDocument">
        <vue-office-docx 
          :src="previewDocument" 
          style="height: 100%;"
          @rendered="onPreviewRendered"
        />
      </div>
    </el-card>

    <el-card class="instructions-card">
      <div slot="header">
        <span>使用说明</span>
      </div>

      <div class="instructions-content">
        <h3>模板变量说明：</h3>
        <p>在Word模板中使用以下变量进行替换：</p>
        <ul>
          <li><strong>{name}</strong> - 姓名</li>
          <li><strong>{position}</strong> - 职位</li>
          <li><strong>{company}</strong> - 公司名称</li>
          <li><strong>{date}</strong> - 日期</li>
          <li><strong>{salary}</strong> - 薪资</li>
          <li><strong>{remarks}</strong> - 备注信息</li>
        </ul>

        <h3>操作步骤：</h3>
        <ol>
          <li>下载示例模板或创建自己的Word模板</li>
          <li>在模板中使用上述变量占位符</li>
          <li>上传模板文件并填写表单数据</li>
          <li>点击"生成文档"按钮</li>
          <li>预览或下载生成的Word文档</li>
        </ol>
      </div>
    </el-card>
  </div>
</template>

<script>
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import { saveAs } from "file-saver";
import VueOfficeDocx from '@vue-office/docx';

/**
 * Word模板生成组件
 * 使用docxtemplater库实现动态Word文档生成，支持实时预览
 */
export default {
  name: "DocxTemplate",
  
  components: {
    VueOfficeDocx
  },

  data() {
    return {
      form: {
        name: "",
        position: "",
        company: "",
        date: "",
        salary: 0,
        remarks: "",
      },
      templateFiles: [],
      templateFile: null,
      previewUrl: null,
      previewDocument: null, // 用于预览的文档数据
      showPreview: false,   // 是否显示预览
      generating: false,
      generatedDocument: null,
      
      // 本地模板相关数据
      templateSource: 'upload', // 模板来源：upload-上传，local-本地
      selectedLocalTemplate: '', // 选中的本地模板
      localTemplates: [
        {
          value: 'dez.docx',
          label: '二票',
          description: '二票模板'
        },
        {
          value: 'offer-template.docx',
          label: '录用通知书模板',
          description: '标准录用通知书模板'
        },
        {
          value: 'contract-template.docx',
          label: '劳动合同模板',
          description: '标准劳动合同模板'
        },
        {
          value: 'certificate-template.docx',
          label: '证明模板',
          description: '各类证明文件模板'
        }
      ]
    };
  },

  methods: {
    async getTestDoc() {
      if (!this.templateFile) {
        this.$message.warning("请先上传模板文件");
        return;
      }

      this.generating = true;

      try {
        const dataD = {
          ywh: "12",
          bbh: "",
          ssjTitle: "泉州供电公司",
          deptBmDisp: "部门",
          deptGzbzDisp: "班组1",
          userGzfzrDisp: "负责人",
          gzbry: "he,张,珺，墚",
          gzxlmc: "高级工程师",
          gzbryrs: 10,
          tableConfig4Data: [
            { gzdd: "地任务任务任务任务任务任务任务任务任务任务任务任务任务点", gzrw: "任务任务任务任务任务任务任务任务任务任务哈哈哈哈哈哈哈哈哈" },
            { gzdd: "地任务任务任务任务任务任务任务任务任务任务任务点", gzrw: "任务任务任务任务任务任务任务任务任务任务" },
            { gzdd: "地任务任务任务任务任务任务任务任务任务任务点", gzrw: "任务任务任务任务任务任务任务任务任务任务" },
          ],
          printTime: "2020-11-11 12:00:00",
        };
        // 读取模板文件
        const arrayBuffer = await this.readFileAsArrayBuffer(this.templateFile);

        // 使用PizZip加载文档
        const zip = new PizZip(arrayBuffer);

        // 创建docxtemplater实例
        const doc = new Docxtemplater();
        doc.loadZip(zip);

        // 设置模板数据
        doc.setData(dataD);

        // 渲染文档
        doc.render();

        // 生成输出文档
        const out = doc.getZip().generate({
          type: "blob",
          mimeType:
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        });

        this.generatedDocument = out;
        this.previewUrl = URL.createObjectURL(out);
        this.previewDocument = out; // 设置预览文档

        this.$message.success("文档生成成功！");
      } catch (error) {
        console.error("文档生成失败:", error);
        this.$message.error("文档生成失败：" + error.message);
      } finally {
        this.generating = false;
      }
    },
    
    /**
     * 处理模板文件上传
     * @param {Object} file - 上传的文件对象
     * @param {Array} fileList - 文件列表
     */
    handleTemplateUpload(file, fileList) {
      console.log("文件上传:", file);
      console.log("文件列表:", fileList);
      this.templateFiles = fileList.slice(-1); // 只保留最后一个文件
      this.templateFile = file.raw;
      console.log("templateFile设置:", this.templateFile);
      this.previewUrl = null;
      this.previewDocument = null;
      this.showPreview = false;
      this.generatedDocument = null;
    },

    /**
     * 生成Word文档
     * 使用docxtemplater处理模板和数据
     */
    async generateDocument() {
      if (!this.templateFile) {
        this.$message.warning("请先上传模板文件");
        return;
      }

      this.generating = true;

      try {
        // 读取模板文件
        const arrayBuffer = await this.readFileAsArrayBuffer(this.templateFile);

        // 使用PizZip加载文档
        const zip = new PizZip(arrayBuffer);

        // 创建docxtemplater实例
        const doc = new Docxtemplater();
        doc.loadZip(zip);

        // 设置模板数据
        doc.setData(this.form);

        // 渲染文档
        doc.render();

        // 生成输出文档
        const out = doc.getZip().generate({
          type: "blob",
          mimeType:
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        });

        this.generatedDocument = out;
        this.previewUrl = URL.createObjectURL(out);
        this.previewDocument = out; // 设置预览文档

        this.$message.success("文档生成成功！");
      } catch (error) {
        console.error("文档生成失败:", error);
        this.$message.error("文档生成失败：" + error.message);
      } finally {
        this.generating = false;
      }
    },

    /**
     * 预览文档渲染完成回调
     */
    onPreviewRendered() {
      console.log("Word文档预览渲染完成");
    },

    /**
     * 下载生成的文档
     */
    downloadDocument() {
      if (!this.generatedDocument) {
        this.$message.warning("请先生成文档");
        return;
      }

      const fileName = `offer_${this.form.name}_${new Date().getTime()}.docx`;
      saveAs(this.generatedDocument, fileName);
    },

    /**
     * 下载示例模板
     */
    downloadTemplate() {
      // 创建一个简单的示例模板
      const templateContent = `
        <!DOCTYPE html>
        <html>
        <head>
            <title>示例模板</title>
        </head>
        <body>
            <h1>录用通知书</h1>
            <p>尊敬的 {name} 先生/女士：</p>
            <p>我们很高兴地通知您，{company} 公司决定录用您担任 {position} 职位。</p>
            <p>您的薪资为：{salary} 元/月</p>
            <p>入职日期：{date}</p>
            <p>备注：{remarks}</p>
            <p>我们期待您的加入！</p>
            <p>此致</p>
            <p>敬礼！</p>
            <p>{company} 人力资源部</p>
        </body>
        </html>
      `;

      const blob = new Blob([templateContent], { type: "text/html" });
      saveAs(blob, "示例模板.html");

      this.$message.info("请将示例内容复制到Word文档中保存为.docx格式");
    },

    /**
     * 读取文件为ArrayBuffer
     * @param {File} file - 文件对象
     * @returns {Promise<ArrayBuffer>} ArrayBuffer
     */
    readFileAsArrayBuffer(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (e) => resolve(e.target.result);
        reader.onerror = (error) => reject(error);
        reader.readAsArrayBuffer(file);
      });
    },

    /**
     * 处理模板来源切换
     * @param {string} source - 模板来源
     */
    handleTemplateSourceChange(source) {
      this.templateFile = null;
      this.templateFiles = [];
      this.selectedLocalTemplate = '';
      this.previewUrl = null;
      this.previewDocument = null;
      this.showPreview = false;
      this.generatedDocument = null;
    },

    /**
     * 加载本地模板文件
     * @param {string} templateName - 模板文件名
     * @returns {Promise<File>} 模板文件对象
     */
    async loadLocalTemplate(templateName) {
      try {
        // 使用require.context或import.meta.glob来加载本地文件
        // 这里使用fetch来获取模板文件
        const response = await fetch(`/templates/${templateName}`);
        if (!response.ok) {
          throw new Error(`模板文件加载失败: ${response.statusText}`);
        }
        
        const blob = await response.blob();
        return new File([blob], templateName, { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
      } catch (error) {
        console.error('加载本地模板失败:', error);
        this.$message.error(`加载模板失败: ${error.message}`);
        throw error;
      }
    },

    /**
     * 生成文档（支持本地模板和上传模板）
     */
    async generateDocument() {
      if (this.templateSource === 'upload' && !this.templateFile) {
        this.$message.warning("请先上传模板文件");
        return;
      }

      if (this.templateSource === 'local' && !this.selectedLocalTemplate) {
        this.$message.warning("请先选择本地模板");
        return;
      }

      this.generating = true;

      try {
        let templateFile;
        
        if (this.templateSource === 'upload') {
          templateFile = this.templateFile;
        } else {
          // 加载本地模板
          templateFile = await this.loadLocalTemplate(this.selectedLocalTemplate);
        }

        if (!templateFile) {
          throw new Error('模板文件加载失败');
        }

        // 读取模板文件
        const arrayBuffer = await this.readFileAsArrayBuffer(templateFile);

        // 使用PizZip加载文档
        const zip = new PizZip(arrayBuffer);

        // 创建docxtemplater实例
        const doc = new Docxtemplater();
        doc.loadZip(zip);

        // 准备图片数据（如果存在）
        const imageData = {};
        if (this.form.avatar) {
          // 提取Base64数据部分
          const avatarBase64 = this.form.avatar.split(',')[1];
          imageData.avatar = {
            data: avatarBase64,
            extension: '.png', // 假设为PNG格式
            width: 100,
            height: 100
          };
        }

        if (this.form.logo) {
          // 提取Base64数据部分
          const logoBase64 = this.form.logo.split(',')[1];
          imageData.logo = {
            data: logoBase64,
            extension: '.png', // 假设为PNG格式
            width: 150,
            height: 50
          };
        }

        // 设置模板数据（包含图片）
        doc.setData({
          ...this.form,
          ...imageData
        });

        // 渲染文档
        doc.render();

        // 生成输出文档
        const out = doc.getZip().generate({
          type: "blob",
          mimeType:
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        });

        this.generatedDocument = out;
        this.previewUrl = URL.createObjectURL(out);
        this.previewDocument = out; // 设置预览文档

        this.$message.success("文档生成成功！");
      } catch (error) {
        console.error("文档生成失败:", error);
        this.$message.error("文档生成失败：" + error.message);
      } finally {
        this.generating = false;
      }
    },

    /**
     * 重置表单（包含图片数据）
     */
    resetForm() {
      this.form = {
        name: "",
        position: "",
        company: "",
        date: "",
        salary: 0,
        avatar: "",
        logo: "",
        remarks: "",
      };
      this.templateFiles = [];
      this.templateFile = null;
      this.imageFiles = [];
      this.logoFiles = [];
      this.previewUrl = null;
      this.previewDocument = null;
      this.showPreview = false;
      this.generatedDocument = null;
      this.templateSource = 'upload';
      this.selectedLocalTemplate = '';
    },
  },
};
</script>

<style lang="scss" scoped>
.app-container {
  padding: 20px;

  .header {
    text-align: center;
    margin-bottom: 30px;

    h1 {
      color: #303133;
      margin-bottom: 10px;
    }

    .description {
      color: #606266;
      font-size: 14px;
    }
  }

  .main-card,
  .preview-card,
  .instructions-card {
    margin-bottom: 20px;
  }

  .demo-form {
    max-width: 600px;
  }

  .preview-content {
    text-align: center;
    padding: 20px;

    p {
      margin-bottom: 15px;
      color: #606266;
    }
  }

  .word-preview {
    border: 1px solid #ebeef5;
    border-radius: 4px;
    overflow: auto; /* 改为auto以显示滚动条 */
    height: 80vh; /* 使用视口高度，确保预览区域足够大 */
    min-height: 600px; /* 最小高度保证基本显示 */
  }

  /* 添加全局样式覆盖vue-office/docx的表格样式 */
  ::v-deep .vue-office-docx {
    /* 表格居中样式 */
    table {
      margin: 0 auto !important;
      border-collapse: collapse;
      width: auto !important;
    }
    
    /* 表格单元格居中 */
    // td, th {
    //   text-align: center !important;
    //   vertical-align: middle !important;
    //   padding: 8px 12px !important;
    // }
    
    /* 确保文档内容在容器中居中 */
    // .docx-wrapper {
    //   display: flex !important;
    //   justify-content: center !important;
    //   align-items: flex-start !important;
    //   min-height: 100% !important;
    // }
    
    /* 文档容器样式 */
    // .docx-container {
    //   margin: 0 auto !important;
    //   max-width: 100% !important;
    // }
  }

  .instructions-content {
    line-height: 1.6;

    h3 {
      color: #303133;
      margin-bottom: 10px;
    }

    p,
    ul,
    ol {
      color: #606266;
      margin-bottom: 15px;
    }

    ul,
    ol {
      padding-left: 20px;
    }

    li {
      margin-bottom: 5px;
    }

    strong {
      color: #409eff;
    }
  }

  .upload-demo {
    ::v-deep .el-upload {
      display: block;
    }
  }
}
</style>
